﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

using Styx.WoWInternals.DBC;
using Styx.WoWInternals.WoWObjects;
using Styx.WoWInternals;
using Styx.Common;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.Pathing;
using Styx;
using System.Diagnostics;
using System.Threading;
using System.IO;
using Styx.CommonBot;
using System.Windows.Forms;
using Styx.CommonBot.Inventory;

namespace KingWoW
{
    class FireMageCombatClass : KingWoWAbstractBaseClass
    {

        private static string Name = "KingWoW FireMage'";

        #region CONSTANT AND VARIABLES

        //START OF CONSTANTS ==============================
        private string[] StealBuffs = { "Innervate", "Hand of Freedom", "Hand of Protection", "Regrowth", "Rejuvenation", "Lifebloom", "Renew", 
                                      "Hand of Salvation", "Power Infusion", "Power Word: Shield", "Arcane Power", "Hot Streak!", /*"Avenging Wrath",*/ 
                                      "Elemental Mastery", "Nature's Swiftness", "Divine Plea", "Divine Favor", "Icy Veins", "Ice Barrier", "Holy Shield", 
                                      "Divine Aegis", "Bloodlust", "Time Warp", "Brain Freeze"};
        private static bool IsCRPaused = false;
        private const bool LOGGING = true;
        private const bool DEBUG = false;
        private const bool TRACE = false;
        private static KingWoWUtility utils = null;
        private Movement movement = null;
        private ExtraUtils extra = null;
        WoWUnit flamestrikeCandidateTarget = null;
        WoWUnit BlastWaveCandidateTarget = null;
        WoWUnit target = null;
        private WoWUnit tank = null;
        private WoWUnit off_tank = null;
        private WoWUnit lastTank = null;
        private WoWUnit lastOffTank = null;
        private bool SoloBotType = false;
        private string BaseBot = "unknown";
        private DateTime nextTimeRuneOfPowerAllowed;
        private TalentManager talents = null;

        private Random rnd = new Random();
        private int RANDOM_TIME = 0;

        private const string DEBUG_LABEL = "DEBUG";
        private const string TRACE_LABEL = "TRACE";
        private const string TANK_CHANGE = "TANK CHANGED";
        private const string OFF_TANK_CHANGE = "OFF_TANK CHANGED";
        private const string FACING = "FACING";

        //START OF SPELLS AND AURAS ==============================
        private const string DRINK = "Drink";
        private const string FOOD = "Food";

        private const string FROSTFIRE_BOLT = "Frostfire Bolt";
        private const string FROST_NOVA = "Frost Nova";
        private const string FIRE_BLAST = "Fire Blast";
        private const string BLINK = "Blink";
        private const string COUNTERSPELL = "Counterspell";
        private const string FROSTBOLT = "Frostbolt";
        private const string POLYMORPH = "Polymorph";
        private const string ICE_BLOCK = "Ice Block";
        private const string REMOVE_CURSE = "Remove Curse";
        private const string SLOW_FALL = "Slow Fall";
        private const string CONJURE_REFRESHMENT = "Conjure Refreshment";
        private const string FLAMESTRIKE = "Flamestrike";
        private const string MIRROR_IMAGE = "Mirror Image";
        private const string INVISIBILITY = "Invisibility";
        private const string ARCANE_BRILLANCE = "Arcane Brilliance";
        private const string SPELLSTEAL = "Spellsteal";
        private const string DEEP_FREEZE = "Deep Freeze";
        private const string CONJURE_REFRESHMENT_TABLE = "Conjure Refreshment Table";
        private const string TIME_WARP = "Time Warp";
        private const string ALTER_TIME = "Alter Time";
        private const string EVANESCE = "Evanesce";
        private const string METEOR = "Meteor";
        private const string ENHANCED_PYROTECHNICS_BUFF = "Enhanced Pyrotechnics"; 
        private const int ENHANCED_PYROTECHNICS_BUFF_INT = 157644; 
        //END OF SPELLS AND AURAS ==============================

        //TALENTS
        private const string PRESENCE_OF_MIND = "Presence of Mind";
        private const string SCORCH = "Scorch";
        private const string ICE_FLOES = "Ice Floes";
        private const int ICE_FLOES_BUFF = 108839;
        private const string BLAZING_SPEED = "Blazing Speed";
        private const string ICE_BARRIER = "Ice Barrier";
        private const string RING_OF_FROST = "Ring of Frost";
        private const string ICE_WARD = "Ice Ward";
        private const string FROSTJAW = "Frostjaw";
        private const string GREATER_INVISIBILITY = "Greater Invisibility";

        private const string COLD_SNAP = "Cold Snap";
        private const string LIVING_BOMB = "Living Bomb";
        private const string RUNE_OF_POWER = "Rune of Power";
        
        private const string COMBUSTION = "Combustion";
        private const string IGNITE = "Ignite";
        private const string PYROBLAST = "Pyroblast";
        private const string PYROBLAST_PROC = "Pyroblast!";
        private const string HEATING_UP = "Heating Up";
        private const string INFERNO_BLAST = "Inferno Blast";
        private const string FIREBALL = "Fireball";
        private const string DRAGON_BREATH = "Dragon's Breath";
        private const string BLAST_WAVE = "Blast Wave";
        private const string PRISMATIC_CRYSTAL = "Prismatic Crystal";
         

        //END TALENTS
        //END OF CONSTANTS ==============================

        #endregion

        #region Hotkeys
        private static void InitializeHotkey()
        {
            HotkeysManager.Initialize(StyxWoW.Memory.Process.MainWindowHandle);
        }

        private static DateTime nextTime_Pause_Resume_Allowed = DateTime.Now;

        public static void SetnextTime_Pause_Resume_Allowed()
        {
            //1 seconds avoid duuble cast
            nextTime_Pause_Resume_Allowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 1000);
        }

        private static Hotkey RegisterHotkeyAssignment(string name, Keys key, Action<Hotkey> callback)
        {
            Keys keyCode = key & Keys.KeyCode;
            ModifierKeys mods = ModifierKeys.NoRepeat;

            if ((key & Keys.Shift) != 0)
                mods |= ModifierKeys.Shift;
            if ((key & Keys.Alt) != 0)
                mods |= ModifierKeys.Alt;
            if ((key & Keys.Control) != 0)
                mods |= ModifierKeys.Control;

            return HotkeysManager.Register(name, keyCode, mods, callback);
        }

        private static void RegisterHotkeys()
        {
            RegisterHotkeyAssignment("Routine Pause", (Keys)FireMageSettings.Instance.PauseKey, hk =>
            {
                if (nextTime_Pause_Resume_Allowed < DateTime.Now)
                {
                    if (!IsCRPaused)
                    {
                        IsCRPaused = true;
                        if (ExtraUtilsSettings.Instance.ViewChatMessages) 
                            Lua.DoString(@"print('\124cFFE61515 Paused!')");
                        Logging.Write("KingWoW Routine Paused!");
                    }
                    else
                    {
                        IsCRPaused = false;
                        if (ExtraUtilsSettings.Instance.ViewChatMessages) 
                            Lua.DoString(@"print('\124cFF15E61C Resumed!')");
                        Logging.Write("KingWoW Routine Resumed!");
                    }
                    SetnextTime_Pause_Resume_Allowed();
                }
            });
            RegisterHotkeyAssignment("AvoidAOE", (Keys)FireMageSettings.Instance.AvoidAOEKey, hk =>
            {
                FireMageSettings.Instance.AvoidAOE = !FireMageSettings.Instance.AvoidAOE;
                if (FireMageSettings.Instance.AvoidAOE)
                {
                    if (ExtraUtilsSettings.Instance.ViewChatMessages) 
                        Lua.DoString(@"print('AvoidAOE \124cFF15E61C Enabled!')");
                    Logging.Write("AvoidAOE Enabled!");
                }

                else
                {
                    if (ExtraUtilsSettings.Instance.ViewChatMessages)
                        Lua.DoString(@"print('AvoidAOE \124cFFE61515 Disabled!')");
                    Logging.Write("AvoidAOE Disabled!");
                }

            });

            RegisterHotkeyAssignment("BurstKey", (Keys)FireMageSettings.Instance.BurstKey, hk =>
            {
                if (ExtraUtilsSettings.Instance.ViewChatMessages)
                    Lua.DoString(@"print('BURST!!!')");
                Logging.Write("BurstKeyPressed!");

                BurstModeActivated = true;
                BurstTimer.AutoReset = false;
                BurstTimer.Interval = 10000;
                BurstTimer.Start();
            });
        }

        private static bool BurstModeActivated = false;
        private static System.Timers.Timer BurstTimer = new System.Timers.Timer();

        private bool BurstHotkeyHandle()
        {
            if (BurstModeActivated)
            {
                if (utils.CanCast(MIRROR_IMAGE) && FireMageSettings.Instance.CDUseMirrorImage == FireMageSettings.CDUseType.OnBURSTHOTKEY)
                {
                    utils.LogActivity("BURST HOTKEY TRY CAST:" + MIRROR_IMAGE);
                    utils.Cast(MIRROR_IMAGE);
                }
                if (utils.CanCast(PRISMATIC_CRYSTAL) && FireMageSettings.Instance.PrismaticCrystalOnlyOnBurst)
                {
                    if (Me.CurrentTarget != null && Me.CurrentTarget.Attackable && Me.CurrentTarget.IsValid)
                    {
                        utils.LogActivity("BURST HOTKEY TRY CAST:" + PRISMATIC_CRYSTAL, Me.CurrentTarget.SafeName);
                        utils.Cast(PRISMATIC_CRYSTAL, Me.CurrentTarget);
                        SpellManager.ClickRemoteLocation(Me.CurrentTarget.Location);
                    }
                }
            }
            return false;
        }

        private static void RemoveHotkeys()
        {
            HotkeysManager.Unregister("Routine Pause");
            HotkeysManager.Unregister("AvoidAOE");
            HotkeysManager.Unregister("BurstKey");
        }

        private static void ReRegisterHotkeys()
        {
            RemoveHotkeys();
            RegisterHotkeys();
        }
        #endregion

        public int GetTargetIgniteStrength()
        {
            string command = "return select(15,UnitDebuff(\"target\", \"Ignite\", nil, \"PLAYER\"))";
            int baseDmg = Lua.GetReturnVal<int>(command, 0);
            return baseDmg;       
        }

        private bool Decursing()
        {
            if (FireMageSettings.Instance.UseDecurse && utils.CanCast(REMOVE_CURSE))
            {
                WoWUnit player = null;
                if (utils.NeedsDeCurse(Me))
                    player = Me;
                else player = utils.GetDecurseTarget(40f);

                if (player != null && player.Distance - player.CombatReach -1  <= 40f && player.InLineOfSpellSight)
                {
                    utils.LogActivity(REMOVE_CURSE, player.Class.ToString());
                    return utils.Cast(REMOVE_CURSE, player);
                }
            }
            return false;
        }

        public FireMageCombatClass()
        {
            utils = new KingWoWUtility();
            movement = new Movement();
            extra = new ExtraUtils();
            tank = null;
            lastTank = null; ;
            SoloBotType = false;
            BaseBot = "unknown";
            nextTimeRuneOfPowerAllowed = DateTime.Now;
            nextTimeTryReviveAllowed = DateTime.Now;
            talents = new TalentManager();
            BurstTimer.Elapsed += BurstTimer_Elapsed;
        }

        void BurstTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                Lua.DoString(@"print('BURST ENDS!!!')");
            Logging.Write("BurstModeEnd!");
            BurstModeActivated = false;
        }

        public override bool Combat
        {
            get
            {
                if ((Me.Mounted && !FireMageSettings.Instance.AutoDismountOnCombat)
                    || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || Me.Silenced
                    || (!ExtraUtilsSettings.Instance.FastRotation && (utils.IsGlobalCooldown() || Me.IsCasting))
                    || utils.isAuraActive(DRINK) || utils.isAuraActive(FOOD) || Me.IsChanneling || IsCRPaused)
                    return false;

                tank = utils.SimpleGetTank(40f);
                if (tank == null || !tank.IsValid || !tank.IsAlive) tank = Me;

                if (tank != null && (lastTank == null || lastTank.Guid != tank.Guid))
                {
                    lastTank = tank;
                    utils.LogActivity(TANK_CHANGE, tank.Class.ToString());
                } off_tank = utils.SimpleGetOffTank(40f, tank);
                if (off_tank != null && (lastOffTank == null || lastOffTank.Guid != off_tank.Guid))
                {
                    lastOffTank = off_tank;
                    utils.LogActivity(OFF_TANK_CHANGE, off_tank.Class.ToString());
                }
                return CombatRotation();
            }
        }

        public override bool Pulse
        {
            get
            {
                if (Me.IsDead) return MyDeath();
                if (Me.Combat || (Me.Mounted && !FireMageSettings.Instance.AutoDismountOnCombat)
                    || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || Me.Silenced || utils.IsGlobalCooldown()
                    || utils.MeIsChanneling || Me.IsCasting
                    || utils.isAuraActive(DRINK) || utils.isAuraActive(FOOD) || IsCRPaused)
                    return false;
                tank = utils.SimpleGetTank(40f);
                if (tank == null || !tank.IsValid || !tank.IsAlive) tank = Me;

                if (tank != null && (lastTank == null || lastTank.Guid != tank.Guid))
                {
                    lastTank = tank;
                    utils.LogActivity(TANK_CHANGE, tank.SafeName);
                }
                off_tank = utils.SimpleGetOffTank(40f, tank);
                if (off_tank != null && (lastOffTank == null || lastOffTank.Guid != off_tank.Guid))
                {
                    lastOffTank = off_tank;
                    utils.LogActivity(OFF_TANK_CHANGE, off_tank.SafeName);
                }
                if (!Me.Combat && ((tank != null && tank.Combat) || (off_tank != null && off_tank.Combat)))
                    return CombatRotation();
                return false;
            }
        }

        private DateTime nextTimeTryReviveAllowed;

        public void SetNextTimeTryRevive()
        {
            //2 seconds avoid duuble cast
            nextTimeTryReviveAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 3000);
        }

        private bool MyDeath()
        {
            if (SoloBotType && Me.IsDead && !Me.IsGhost && nextTimeTryReviveAllowed < DateTime.Now)
            {
                Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                SetNextTimeTryRevive();
            }
            return false;
        }

        public override bool Pull
        {
            get
            {
                target = Me.CurrentTarget;
                if (target != null && target.IsDead)
                {
                    Me.ClearTarget();
                    target = utils.getTargetToAttack(40, tank, false, ExtraUtilsSettings.Instance.UseBossLogic);
                    target.Target();
                }
                if ((SoloBotType || FireMageSettings.Instance.movementEnabled) && Me.CurrentTarget != null && Me.IsMoving && Me.CurrentTarget.InLineOfSpellSight && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= FireMageSettings.Instance.PullDistance)
                {
                    Navigator.PlayerMover.MoveStop();
                }
                if (target != null && !target.IsFriendly && target.Attackable && !target.IsDead && !IsCRPaused)
                {
                    if (!target.InLineOfSpellSight || target.Distance > FireMageSettings.Instance.PullDistance)
                    {
                        movement.KingHealMove(target, FireMageSettings.Instance.PullDistance);
                    }
                    if (utils.CanCast(FIREBALL, target)/*&& !Me.IsMoving*/)
                    {
                        if (!Me.IsMoving && !Me.IsFacing(target))
                        {
                            utils.LogActivity(FACING, target.SafeName);
                            Me.SetFacing(target);
                        }

                        utils.LogActivity(FIREBALL, target.SafeName);
                        return utils.Cast(FIREBALL, target);
                    }
                }
                return false;
            }
        }

        public override bool Initialize
        {
            get
            {
                Logging.Write("Ciao " + Me.Class.ToString());
                Logging.Write("Welcome to " + Name + " custom class");
                Logging.Write("Tanks All HonorBuddy Forum developers for code inspiration!");
                Logging.Write("Powered by Attilio76");
                BotEvents.OnBotStartRequested += new BotEvents.OnBotStartStopRequestedDelegate(BotEvents_OnBotStart);
                InitializeHotkey();
                RegisterHotkeys();
                Logging.Write("************ XML CONFIGURATION ************");
                Logging.Write(FireMageSettings.Instance.GetXML().ToString());
                Logging.Write("*******************************************");
                Logging.Write("*******************************************");
                Logging.Write("*******************************************");
                Logging.Write("*******************************************");
                Logging.Write("************ EXTRA CONFIGURATION ************");
                Logging.Write(ExtraUtilsSettings.Instance.GetXML().ToString());
                Logging.Write("*******************************************");
                return true; ;
            }
        }

        void BotEvents_OnBotStart(EventArgs args)
        {
            ReRegisterHotkeys();
            talents.Update();
            BotUpdate();
        }

        public override bool UpdateTalentAndGlyph
        {
            get
            {
                ReRegisterHotkeys();
                talents.Update();
                BotUpdate();
                return true;

            }
        }

        public override bool NeedCombatBuffs { get { return Buff(); } }

        public override bool NeedPreCombatBuffs { get { return Buff(); } }

        public override bool NeedPullBuffs { get { return Buff(); } }

        public override bool NeedRest
        {
            get
            {
                if (Me.IsDead || Me.Mounted || Me.InVehicle || (Me.HealthPercent >= 100 && Me.ManaPercent >= 100)) return false;
                if (utils.IsEatingOrDrinking() )
                    return true;
                if (!Me.Combat && !Me.IsCasting && !utils.IsGlobalCooldown() && !utils.GotMagefood && utils.CanCast(CONJURE_REFRESHMENT))
                {
                    utils.LogActivity(CONJURE_REFRESHMENT);
                    return utils.Cast(CONJURE_REFRESHMENT);
                }
                if (Me.ManaPercent <= FireMageSettings.Instance.ManaPercent
                    && !Me.Combat && !Me.IsMoving && !utils.IsEatingOrDrinking())
                {
                    WoWItem mydrink = Consumable.GetBestDrink(false);
                    if (mydrink != null)
                    {
                        utils.LogActivity("Drinking");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return true;
                    }
                    return true;
                }
                if (Me.HealthPercent <= FireMageSettings.Instance.HealthPercent
                    && !Me.Combat && !Me.IsMoving && !utils.IsEatingOrDrinking())
                {
                    WoWItem myfood = Consumable.GetBestFood(false);
                    if (myfood != null)
                    {
                        utils.LogActivity("Eating");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return true;
                    }
                    return true;
                }
                return false;
            }
        }

        public void SetNextTimeRuneOfPower()
        {
            //3 seconds wait to avoid popping 2 rune of frost cause has high priority
            nextTimeRuneOfPowerAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 3000);
        }

        private bool PriorityBuff()
        {
            if (FireMageSettings.Instance.UseRuneOfPower && !Me.IsMoving && nextTimeRuneOfPowerAllowed < DateTime.Now && !utils.isAuraActive(RUNE_OF_POWER, Me) && Me.Combat && utils.CanCast(RUNE_OF_POWER))
            {
                utils.LogActivity(RUNE_OF_POWER);
                utils.Cast(RUNE_OF_POWER);
                SetNextTimeRuneOfPower();
                return SpellManager.ClickRemoteLocation(Me.Location);
            }

            if (Me.Combat && FireMageSettings.Instance.UseIcebarrier && utils.CanCast(ICE_BARRIER) && Me.HealthPercent <= FireMageSettings.Instance.IcebarrierHP && !utils.isAuraActive(ICE_BARRIER))
            {
                utils.LogActivity(ICE_BARRIER);
                return utils.Cast(ICE_BARRIER);
            }
            
            if (FireMageSettings.Instance.IceWardOnTank && Me.Combat && (tank != null && tank.Combat) && utils.CanCast(ICE_WARD) &&
                !utils.isAuraActive(ICE_WARD, tank) && tank != null && tank.IsAlive && tank.Distance < 40 &&
                tank.InLineOfSpellSight)
            {
                utils.LogActivity(ICE_WARD, tank.Class.ToString());
                return utils.Cast(ICE_WARD, tank);
            }
            return false;
        }

        private bool Buff()
        {
            if (Me.Mounted || IsCRPaused || Me.InVehicle
                    || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || Me.Silenced
                    || utils.isAuraActive(DRINK) || utils.isAuraActive(FOOD) || Me.IsChanneling
                /*|| utils.MeIsCastingWithLag()*/) 
                return false;
            
            //arcane brillance
            if (FireMageSettings.Instance.AutoBuffBrillance && !utils.isAuraActive(ARCANE_BRILLANCE) && utils.CanCast(ARCANE_BRILLANCE))
            {
                utils.LogActivity(ARCANE_BRILLANCE);
                return utils.Cast(ARCANE_BRILLANCE);
            }

            
            return false;
        }

        private void SetTargetToAttack()
        {
            if (FireMageSettings.Instance.TargetTypeSelected == FireMageSettings.TargetType.AUTO)
            {
                if (ExtraUtilsSettings.Instance.provinGround_Targeting)
                    target = utils.getAnyTargetToAttack(40f);
                else
                    target = utils.getTargetToAttack(40, tank, false, ExtraUtilsSettings.Instance.UseBossLogic);
                if (target != null)
                    target.Target();
            }
            else
                target = Me.CurrentTarget;
        }

        private bool Interrupt()
        {
            if (FireMageSettings.Instance.AutoInterrupt)
            {
                WoWUnit InterruptTargetCandidate = Me.FocusedUnit;
                if (InterruptTargetCandidate == null || InterruptTargetCandidate.IsFriendly || InterruptTargetCandidate.IsDead
                    || !InterruptTargetCandidate.Attackable || !InterruptTargetCandidate.InLineOfSpellSight
                    || InterruptTargetCandidate.Distance - InterruptTargetCandidate.CombatReach - 1 > 40f)
                {
                    if (Me.CurrentTarget != null && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= 40f && Me.CurrentTarget.InLineOfSpellSight)
                        InterruptTargetCandidate = Me.CurrentTarget;
                    else if (target != null && target.Distance - target.CombatReach - 1 <= 40f && target.InLineOfSpellSight)
                        InterruptTargetCandidate = target;
                }
                if (InterruptTargetCandidate != null && (InterruptTargetCandidate.IsCasting || InterruptTargetCandidate.IsChanneling)
                    && InterruptTargetCandidate.CanInterruptCurrentSpellCast && utils.CanCast(COUNTERSPELL, InterruptTargetCandidate)
                    && Me.IsFacing(InterruptTargetCandidate)
                    && InterruptTargetCandidate.Distance - InterruptTargetCandidate.CombatReach - 1 <= 40f
                    && InterruptTargetCandidate.InLineOfSpellSight)
                {
                    RANDOM_TIME = rnd.Next(FireMageSettings.Instance.Interrupt_MIN_Time, FireMageSettings.Instance.Interrupt_MAX_Time);

                    if (InterruptTargetCandidate.CurrentCastStartTime.AddMilliseconds(RANDOM_TIME) <= DateTime.Now)
                    {
                        utils.LogActivity(COUNTERSPELL, InterruptTargetCandidate.SafeName);
                        return utils.Cast(COUNTERSPELL, InterruptTargetCandidate);
                    }
                }
            }
            return false;
        }

        private bool ProcWork()
        {
            if (Me.IsFacing(target))
            {
                if ((utils.isAuraActive(PYROBLAST_PROC) && utils.isAuraActive(HEATING_UP))
                        || (Me.HasAura(PYROBLAST_PROC) && Me.GetAuraByName(PYROBLAST_PROC).TimeLeft.TotalMilliseconds <= 2000) 
                        || (utils.isAuraActive(PYROBLAST_PROC) && !utils.isAuraActive(HEATING_UP) /*&& !utils.CanCast(INFERNO_BLAST)*/)
                    /*&& utils.CanCast(PYROBLAST, target)*/)
                {
                    if (PrismaticCrystal()) return true;
                    else
                    {
                        utils.LogActivity(PYROBLAST, target.SafeName);
                        return utils.Cast(PYROBLAST, target);
                    }
                }

                if (!(utils.isAuraActive(HEATING_UP) && utils.isAuraActive(PYROBLAST_PROC)) && (utils.isAuraActive(HEATING_UP) || utils.PlayerCountBuff(ENHANCED_PYROTECHNICS_BUFF_INT)>=3) && utils.CanCast(INFERNO_BLAST))
                {
                    utils.LogActivity(INFERNO_BLAST, target.SafeName);
                    return utils.Cast(INFERNO_BLAST, target);
                }
                
                if (utils.isAuraActive(PRESENCE_OF_MIND) && !utils.isAuraActive(PYROBLAST_PROC) && utils.CanCast(PYROBLAST, target))
                {
                    utils.LogActivity("PoM detected! instant PYROBLAST", target.SafeName);
                    return utils.Cast(PYROBLAST, target);
                }

                
                if (talents.IsSelected(21) && utils.CanCast(METEOR) && !FireMageSettings.Instance.AvoidAOE)
                {
                    WoWUnit MeteorCandidateTarget = utils.EnemyInRangeWithMobsAround(40, 10, FireMageSettings.Instance.MeteorCount, false, ExtraUtilsSettings.Instance.provinGround_Targeting);
                    if (MeteorCandidateTarget == null && FireMageSettings.Instance.MeteorOnSingle)
                        MeteorCandidateTarget = target;
                    if (!MeteorCandidateTarget.IsMoving)
                    {
                        utils.LogActivity(METEOR, MeteorCandidateTarget.SafeName);
                        utils.Cast(METEOR, MeteorCandidateTarget);
                        return SpellManager.ClickRemoteLocation(MeteorCandidateTarget.Location);
                    }
                }
            }
            return false;
        }
        private DateTime nextTimeIceFloesAllowed = DateTime.Now;

        public void SetNextTimeIceFloesAllowed()
        {
            //1 seconds wait to avoid popping 2 rune of frost cause has high priority
            nextTimeIceFloesAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 1000);
        }

        private bool BotUpdate()
        {
            if (BaseBot.Equals(BotManager.Current.Name))
                return false;
            if (utils.IsBotBaseInUse("LazyRaider") || utils.IsBotBaseInUse("Tyrael")
                || utils.IsBotBaseInUse("Raid Bot") || utils.IsBotBaseInUse("Enyo"))
            {
                SoloBotType = false;
                BaseBot = BotManager.Current.Name;
                Logging.Write("Base bot detected: " + BotManager.Current.Name);
                return true;
            }

            Logging.Write("Base bot detected: " + BotManager.Current.Name);
            SoloBotType = true;
            BaseBot = BotManager.Current.Name;
            return true;
        }

        private bool Defensivececk()
        {

            if (Me.Combat && FireMageSettings.Instance.EvanesceUse && utils.CanCast(EVANESCE) && Me.HealthPercent < FireMageSettings.Instance.EvanesceHP && !StyxWoW.Me.ActiveAuras.ContainsKey("Hypothermia"))
            {
                utils.LogActivity(EVANESCE, Me.Class.ToString());
                return utils.Cast(EVANESCE);
            }

            if (Me.Combat && FireMageSettings.Instance.IceBlockUse && utils.CanCast(ICE_BLOCK) && Me.HealthPercent < FireMageSettings.Instance.IceBlockHP && !StyxWoW.Me.ActiveAuras.ContainsKey("Hypothermia"))
            {
                utils.LogActivity(ICE_BLOCK, Me.Class.ToString());
                return utils.Cast(ICE_BLOCK);
            }

            if (Me.Combat && FireMageSettings.Instance.ColdSnapUse && utils.CanCast(COLD_SNAP) && Me.HealthPercent < FireMageSettings.Instance.ColdSnapHP)
            {
                utils.LogActivity(COLD_SNAP, Me.Class.ToString());
                return utils.Cast(COLD_SNAP);
            }

            if (Me.Combat && FireMageSettings.Instance.UseFrostNova && utils.CanCast(FROST_NOVA) && (utils.AllAttaccableEnemyMobsInRange(12).Count() >= 1))
            {
                utils.LogActivity(FROST_NOVA);
                utils.Cast(FROST_NOVA);
            }

            if (Me.Combat && FireMageSettings.Instance.UseBlink && utils.CanCast(BLINK) && Me.IsMoving && (utils.AllAttaccableEnemyMobsInRange(12).Count() >= 1))
            {
                utils.LogActivity(BLINK);
                return utils.Cast(BLINK);
            }
            return false;
        }

        private bool SpellSteal()
        {
            if (FireMageSettings.Instance.UseSpellSteal)
            {
                WoWUnit CandidateUnit = null;
                if (Me.FocusedUnit != null && Me.FocusedUnit.Attackable && Me.FocusedUnit.Distance - Me.FocusedUnit.CombatReach -1  <= 30 && Me.FocusedUnit.InLineOfSpellSight)
                    CandidateUnit = Me.FocusedUnit;
                else if (Me.CurrentTarget != null && Me.CurrentTarget.Attackable && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach -1  <= 30 && Me.CurrentTarget.InLineOfSpellSight)
                    CandidateUnit = Me.CurrentTarget;
                if (CandidateUnit != null && utils.CanCast(SPELLSTEAL, CandidateUnit, true))
                    return SpellStealOnUnit(CandidateUnit);
            }

            return false;
        }

        private bool SpellStealOnUnit(WoWUnit u)
        {
            foreach (string spell in StealBuffs)
            {
                if (u.HasAura(spell) && !StyxWoW.Me.HasAura(spell) && StyxWoW.Me.ManaPercent > 40)
                {
                    utils.LogActivity(SPELLSTEAL + spell, u.SafeName);
                    return utils.Cast(SPELLSTEAL, u);
                }
            }
            return false;
        }

        private bool IsViableForPolymorph(WoWUnit unit)
        {
            if (utils.IsCrowdControlledPlayer(unit))
                return false;

            if (unit.CreatureType != WoWCreatureType.Beast && unit.CreatureType != WoWCreatureType.Humanoid)
                return false;

            if (StyxWoW.Me.CurrentTarget != null && StyxWoW.Me.CurrentTarget == unit)
                return false;

            /*if (StyxWoW.Me.GroupInfo.IsInParty && StyxWoW.Me.PartyMembers.Any(p => p.CurrentTarget != null && p.CurrentTarget == unit))
                 return false;*/

            return true;
        }

        private bool Polymorf()
        {
            if (FireMageSettings.Instance.UsePolymorf)
            {
                if (Me.FocusedUnit != null && Me.FocusedUnit.Attackable && Me.FocusedUnit.Distance - Me.FocusedUnit.CombatReach -1  <= 30
                    && Me.FocusedUnit.InLineOfSpellSight && IsViableForPolymorph(Me.FocusedUnit) && utils.CanCast(POLYMORPH, Me.FocusedUnit, true))
                {
                    utils.LogActivity(POLYMORPH, Me.FocusedUnit.SafeName);
                    return utils.Cast(POLYMORPH, Me.FocusedUnit);
                }

            }
            return false;

        }

        private bool spredFireDebuff()
        {
            if (utils.CanCast(INFERNO_BLAST) && target != null && (utils.MyAuraTimeLeft(LIVING_BOMB, target) > 0 || utils.MyAuraTimeLeft(PYROBLAST, target) > 0))
            {
                if (utils.AllAttaccableEnemyMobsInRangeFromTarget(target,10f,ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= FireMageSettings.Instance.AOECount)
                {
                    utils.LogActivity(INFERNO_BLAST, target.SafeName);
                    return utils.Cast(INFERNO_BLAST, target);
                }
            }
            return false;
        }

        private bool Multidot()
        {
            if (FireMageSettings.Instance.MultidotEnabled && utils.CanCast(LIVING_BOMB) /*&& !Me.IsCasting && !utils.IsGlobalCooldown()*/)
            {
                int enemyNumber = 0;
                if (ExtraUtilsSettings.Instance.provinGround_Targeting)
                    enemyNumber = utils.AllAttaccableEnemyMobsInRange(40f, FireMageSettings.Instance.MultidotAvoidCC).Count();
                else
                    enemyNumber = utils.AllAttaccableEnemyMobsInRangeTargettingMyParty(40f, FireMageSettings.Instance.MultidotAvoidCC).Count();
                if (enemyNumber >= FireMageSettings.Instance.Multidot_EnemyNumberMin)
                {
                    WoWUnit TargetForMultidot = null;
                    //apply  ShadowWord:Pain and always refresh it right before the last tick;
                    if (utils.CanCast(LIVING_BOMB) && utils.AllEnemyMobsHasMyAura(LIVING_BOMB).Count() < FireMageSettings.Instance.Multidot_EnemyNumberMax)
                    {
                        TargetForMultidot = utils.NextApplyAuraTarget(LIVING_BOMB, 40f, 10, FireMageSettings.Instance.MultidotAvoidCC);
                        if (TargetForMultidot != null && TargetForMultidot.Distance - TargetForMultidot.CombatReach - 1 <= 40f)
                        {
                            utils.LogActivity("   MULTIDOT LIVING BOMB  ", TargetForMultidot.SafeName);
                            return utils.Buff(LIVING_BOMB, TargetForMultidot);
                        }
                    }
                }
            }
            return false;
        }

        private bool CombatRotation()
        {
            SetTargetToAttack();
            extra.UseHealPotion_Healthstone();
            while (extra.UseRacials()) return true;
            while (extra.UseTrinket1()) return true;
            while (extra.UseTrinket2()) return true;
            extra.UseManaItem();
            while (Defensivececk()) return true;
            while (Interrupt()) return true;
            while (PriorityBuff()) return true;
            while (SpellSteal()) return true;
            while (Polymorf()) return true;
            while (Decursing()) return true;

            if ((SoloBotType || FireMageSettings.Instance.movementEnabled) && Me.CurrentTarget != null && Me.IsMoving && Me.CurrentTarget.InLineOfSpellSight && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= FireMageSettings.Instance.PullDistance)
            {
                Navigator.PlayerMover.MoveStop();
            }


            if (target != null)
            {
                if ((FireMageSettings.Instance.AutofaceTarget || SoloBotType) && !Me.IsMoving)
                {
                    Me.SetFacing(target);
                }
                while (BurstHotkeyHandle()) return true;
                while (ProcWork()) return true;
                while (UseCD()) return true;

                if (FireMageSettings.Instance.CDUseCombustion == FireMageSettings.CDCombustionUseType.COOLDOWN && utils.CanCast(COMBUSTION)
                    && utils.MyAuraTimeLeft(IGNITE, target) > 0 && utils.MyAuraTimeLeft(PYROBLAST, target) > 0 && Me.IsFacing(target))
                {
                    utils.LogActivity("IGNITE POWER:" + GetTargetIgniteStrength());
                    utils.LogActivity(COMBUSTION, target.SafeName);
                    return utils.Cast(COMBUSTION, target);
                }

                if (FireMageSettings.Instance.CDUseCombustion == FireMageSettings.CDCombustionUseType.CONDITION && utils.CanCast(COMBUSTION)
                    && utils.MyAuraTimeLeft(IGNITE, target) > 0 && GetTargetIgniteStrength() >= FireMageSettings.Instance.MinIgniteForCombustion && Me.IsFacing(target))
                {
                    utils.LogActivity("IGNITE POWER:" + GetTargetIgniteStrength());
                    utils.LogActivity(COMBUSTION, target.SafeName);
                    return utils.Cast(COMBUSTION, target);
                }

                /*if (utils.CanCast(INFERNO_BLAST, target) && !FireMageSettings.Instance.AvoidAOE &&
                    utils.AllAttaccableEnemyMobsInRangeFromTarget(target, 10, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= FireMageSettings.Instance.AOECount
                    && utils.MyAuraTimeLeft(IGNITE, target) > 0 && Me.IsFacing(target))
                {
                    utils.LogActivity(INFERNO_BLAST, target.SafeName);
                    return utils.Cast(INFERNO_BLAST, target);
                }*/

                //apply  Living Bomb and refresh it right before or right after the last tick (the expiring Living Bomb will explode in both cases);
                if (utils.CanCast(LIVING_BOMB, target) && !utils.isMyAuraActive(LIVING_BOMB, target) && !(target.IsPlayer && FireMageSettings.Instance.AvoidDOTPlayers))
                {
                    utils.LogActivity(LIVING_BOMB, target.SafeName);
                    return utils.Cast(LIVING_BOMB, target);
                }
                
                
                if (spredFireDebuff()) return true;
                //if (Multidot()) return true;
                

                if (utils.CanCast(BLAST_WAVE) && (!talents.IsSelected(18) || (talents.IsSelected(18) && utils.PlayerCountBuff("Incanter's Flow") == 5) || FireMageSettings.Instance.blastWaveOnCooldown))
                {
                    BlastWaveCandidateTarget = utils.EnemyInRangeWithMobsAround(40, 10, 2, false, ExtraUtilsSettings.Instance.provinGround_Targeting);
                    if (BlastWaveCandidateTarget == null)
                        BlastWaveCandidateTarget = target;
                    if (!Me.IsFacing(BlastWaveCandidateTarget) && !Me.IsMoving)
                        Me.SetFacing(BlastWaveCandidateTarget);
                    if (Me.IsFacing(BlastWaveCandidateTarget))
                    {

                        utils.LogActivity(BLAST_WAVE, BlastWaveCandidateTarget.SafeName);
                        return utils.Cast(BLAST_WAVE, BlastWaveCandidateTarget);
                    }
                }

                if (FireMageSettings.Instance.UseDragonBreath && utils.CanCast(DRAGON_BREATH) && !FireMageSettings.Instance.AvoidAOE && utils.FacingEnemy(15, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= FireMageSettings.Instance.AOECount)
                {
                    utils.LogActivity(DRAGON_BREATH);
                    return utils.Cast(DRAGON_BREATH);
                }

                if (FireMageSettings.Instance.UseRingOfFrost && utils.CanCast(RING_OF_FROST) && target.Distance2DSqr <= 30 * 30)
                {
                    utils.LogActivity(RING_OF_FROST, target.SafeName);
                    utils.Cast(RING_OF_FROST);
                    return SpellManager.ClickRemoteLocation(target.Location);
                }

                //+++++++++++++++++++++++++AOE rotation start+++++++++++++++++++++++++++++++//
                if ((!Me.IsMoving || utils.isAuraActive(ICE_FLOES_BUFF)) && !Me.IsCasting && !utils.IsGlobalCooldown() && FireMageSettings.Instance.UseFlameStrike
                    && SpellManager.CanCast(FLAMESTRIKE, target, true, true) && !FireMageSettings.Instance.AvoidAOE)
                {
                    flamestrikeCandidateTarget = utils.EnemyInRangeWithMobsAroundDontHaveMyDebuff(40, 10, FireMageSettings.Instance.AOECount,FLAMESTRIKE, false, ExtraUtilsSettings.Instance.provinGround_Targeting);
                    if (flamestrikeCandidateTarget != null)
                    {
                        utils.LogActivity(FLAMESTRIKE, flamestrikeCandidateTarget.SafeName);
                        utils.Cast(FLAMESTRIKE);
                        return SpellManager.ClickRemoteLocation(flamestrikeCandidateTarget.Location);
                    }

                }

                if (Multidot()) return true;

                //Cast  Fireball as a filler spell.
                if ((!Me.IsMoving || utils.isAuraActive(ICE_FLOES_BUFF)) && !Me.IsCasting /*&& !utils.IsGlobalCooldown()*/ && Me.IsFacing(target)
                    /*&& SpellManager.CanCast(FIREBALL,target,true,true)*/
                    && !(utils.isAuraActive(PYROBLAST_PROC) && utils.isAuraActive(HEATING_UP)) && !((utils.isAuraActive(PYROBLAST_PROC) || utils.isAuraActive(HEATING_UP)) && utils.CanCast(INFERNO_BLAST)))
                {
                    utils.LogActivity(FIREBALL, target.SafeName);
                    return utils.Cast(FIREBALL, target);
                }

                //+++++++++++++++++++++++DPS moving   START+++++++++++++++++++++++++++
                //ICE_FLOE
                if (FireMageSettings.Instance.autoIceFloes && nextTimeIceFloesAllowed < DateTime.Now && Me.IsMoving && utils.CanCast(ICE_FLOES) && !utils.isAuraActive(ICE_FLOES_BUFF))
                {
                    utils.LogActivity(ICE_FLOES);
                    utils.Cast(ICE_FLOES);
                    SetNextTimeIceFloesAllowed();
                }
                //Scorch
                if ((Me.IsMoving && !utils.isAuraActive(ICE_FLOES_BUFF)) && !Me.IsCasting && !utils.IsGlobalCooldown() && Me.IsFacing(target) && SpellManager.HasSpell(SCORCH)
                    && !(utils.isAuraActive(PYROBLAST_PROC) && utils.isAuraActive(HEATING_UP)) && !((utils.isAuraActive(PYROBLAST_PROC) || utils.isAuraActive(HEATING_UP)) && utils.CanCast(INFERNO_BLAST)))
                {
                    utils.LogActivity(SCORCH, target.SafeName);
                    return utils.Cast(SCORCH, target);
                }
                if ((SoloBotType || FireMageSettings.Instance.movementEnabled) && Me.IsMoving && target.InLineOfSpellSight && target.Distance - target.CombatReach - 1 <= FireMageSettings.Instance.PullDistance)
                {
                    Navigator.PlayerMover.MoveStop();
                }
            }
            else if (FireMageSettings.Instance.movementEnabled && Me.CurrentTarget != null && !Me.CurrentTarget.IsDead && (!Me.CurrentTarget.InLineOfSpellSight || Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 > FireMageSettings.Instance.PullDistance))
            {
                movement.KingHealMove(Me.CurrentTarget, FireMageSettings.Instance.PullDistance);
            }
            return false;
        }

        private bool UseCD()
        {
            if (Me.Combat && Me.GotTarget && !Me.IsMoving)
            {
                if (utils.CanCast(MIRROR_IMAGE) && FireMageSettings.Instance.CDUseMirrorImage == FireMageSettings.CDUseType.COOLDOWN)
                {
                    utils.LogActivity(MIRROR_IMAGE);
                    return utils.Cast(MIRROR_IMAGE);
                }
                
                if (extra.IsTargetBoss())
                {
                    if (utils.CanCast(MIRROR_IMAGE) && FireMageSettings.Instance.CDUseMirrorImage == FireMageSettings.CDUseType.BOSS)
                    {
                        utils.LogActivity(MIRROR_IMAGE);
                        return utils.Cast(MIRROR_IMAGE);
                    }
                }
            }
            return false;
        }

        private bool PrismaticCrystal()
        {
            if (!FireMageSettings.Instance.PrismaticCrystalOnlyOnBurst && talents.IsSelected(20) && !target.IsMoving && !Me.IsMoving && utils.CanCast(PRISMATIC_CRYSTAL)
                && (extra.IsTargetBoss() || utils.AllAttaccableEnemyMobsInRangeFromTarget(target, 8, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= FireMageSettings.Instance.PrismaticCrystalEnemiesNum))
            {
                utils.LogActivity(PRISMATIC_CRYSTAL, target.SafeName);
                utils.Cast(PRISMATIC_CRYSTAL, target);
                return SpellManager.ClickRemoteLocation(target.Location);
            }
            return false;
        }
    }
}
